package com.wechat.network;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import com.swak.exception.RemotingException;
import com.swak.utils.StringUtils;
import com.wechat.Cons;
import com.wechat.command.Command;
import com.wechat.command.CommandResult;
import com.wechat.service.node.NodeService;

public class MultiNetwork extends AbstractNetwork implements Network {

	private final List<Network> robots;
	private final Network remote;

	public MultiNetwork(List<Network> robots, Network remote) {
		this.robots = robots;
		this.remote = remote;
	}

	@Override
	public void connect() throws RemotingException {
		this.remote.connect();
	}

	@Override
	public void close() throws RemotingException {
		this.remote.close();
	}

	@Override
	public CompletionStage<CommandResult> send(Command cmd) {

		// 发送给群
		if (StringUtils.endsWith(cmd.getTo(), Cons.ID_ChatRoom)) {
			return this.sendMessageToRoom(cmd).thenCompose(res -> this.remote.send(cmd));
		}

		// 发送指令给机器人
		if (StringUtils.endsWith(cmd.getTo(), Cons.ID_Robot)) {
			return this.sendMessageToRobot(cmd);
		}

		// 发送指令给远端
		return this.remote.send(cmd);
	}

	// 发布消息 - 发送给群组
	private CompletionStage<CommandResult> sendMessageToRoom(Command message) {
		return this.nodeService.getChatRoom(message.getTo()).thenApply(room -> {

			// 顺序的发送数据
			try {
				String[] userNames = room.getUserNames().split("\\" + Cons.UserNamesSeparateChar);
				for (String userName : userNames) {
					if (StringUtils.endsWith(userName, Cons.ID_Robot)) {
						this.sendMessageToRobot(message.copy().setTo(userName));
					}
				}
			} catch (Exception e) {
				// ig
			}

			// 发送成功
			return CommandResult.success();
		});
	}

	private CompletionStage<CommandResult> sendMessageToRobot(Command message) {
		for (Network network : robots) {
			if (message.getTo().equals(network.name())) {
				return network.send(message);
			}
		}
		return CompletableFuture.completedStage(CommandResult.fail("机器人已销毁！"));
	}

	@Override
	public void bind(NodeService nodeService) {
		super.bind(nodeService);

		// bind service to robots
		for (Network network : robots) {
			network.bind(nodeService);
		}

		// bind service to remote
		this.remote.bind(nodeService);
	}
}
